package storage.v1;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.onpositive.mediawiki.propertyparser.DateParser;
import com.onpositive.mediawiki.propertyparser.DimensionParser;
import com.onpositive.mediawiki.propertyparser.IdentParser;
import com.onpositive.mediawiki.propertyparser.LinkArrayParser;
import com.onpositive.mediawiki.propertyparser.ScalarParser;
import com.onpositive.mediawiki.propertyparser.UnitParser;
import com.onpositive.semantic.model.api.meta.IMeta;
import com.onpositive.semantic.model.api.property.IPropertyProvider;
import com.onpositive.units.AbstractPreprocessor;
import com.onpositive.units.AbstractValueParser;
import com.onpositive.units.ParsedIdent;
import com.onpositive.units.ParsedString;
import com.onpositive.units.ParsedValue;

public class DefaultParserProvider implements IParserProvider {
	
	private static final class NonIdentPartCharsKillingPreprocessor extends
			AbstractPreprocessor {
		@Override
		public String[] preprocess( String[] param, IPropertyProvider propertyProvider, IMeta meta )
		{
			String name = param[0].trim() ;				
			boolean gotAChange = false ;				
			StringBuilder builder = new StringBuilder() ;
			int l = name.length(), prev = 0 ;
			for( int i = 0 ; i < l ; i++ )
			{
				char ch = name.charAt(i) ;
				if( Character.isJavaIdentifierPart(ch) || ch == ' ' )
					continue ;				
				
				gotAChange = true ;
				builder.append( name.substring(prev, i) ) ;
				builder.append("_") ;
				prev = i+1 ;										
			}
			builder.append( name.substring(prev, l)) ;
			
			if( !gotAChange )
				return null;
			
			String newName = builder.toString();
			int i = newName.length() ;
			for( ; i > 0 && newName.charAt(i-1) == '_'; i-- ) ;
			newName = newName.substring(0, i) ;
			param[0] = newName ;
			return param ;
		}
	}

	private static final class IndexKillingPreprocessor extends
			AbstractPreprocessor {
		@Override
		public String[] preprocess( String[] param, IPropertyProvider propertyProvider, IMeta meta ) {
			
			String name = param[0].trim() ;
			
			boolean gotAChange = false ;
			int i = name.length() ;				
			for(  ; i > 0 && Character.isDigit( name.charAt(i-1)) ; i-- ) ;
				gotAChange = true ;
				
			if( !gotAChange )
				return null ;
			
			param[0] = name.substring(0,i) ;
			return param ;
		}
	}

	private static final class MainAltMorePreprocessor extends
			AbstractPreprocessor {
		private String[] needToBeKilledStrings = { "main", "alt", "more", "note" };

		@Override
		public String[] preprocess( String[] param, IPropertyProvider propertyProvider, IMeta meta ) {
			
			String name = param[0].trim() ;
			for( String s : needToBeKilledStrings )
			{
				if( name.startsWith(s) ){
					name = name.substring( s.length() ).trim() ;
					param[0] = name ;
					return param ;
				}
				if( name.endsWith(s)){
					name = name.substring( 0, name.length()-s.length() ).trim() ;
					param[0] = name ;
					return param ;
				}
			}					
			return null;
		}
	}

	public static DefaultParserProvider getInstance(){
		
		return instance ;
	}
	
	private static DefaultParserProvider instance = new DefaultParserProvider() ;
	
	private HashMap<String, AbstractValueParser> parserMap ;
	private ArrayList<AbstractPreprocessor> preprocessors ;
	
	private static AbstractValueParser defaultValueParser = new AbstractValueParser("default-parser") {
		
		@Override
		public ParsedValue parse(String s, IMeta meta, IPropertyProvider propertyProvider, Map<String,Object> metaInfo, String comment) {
			try{
			String line = ParserV2.killWikiRefsLeaveCaptions(s) ;
			return UnitParser.parseStatically(line,meta,propertyProvider, metaInfo, comment) ;
			}
			catch(Exception e){
				return null ;						
			}
		}
	};
	
	public static AbstractValueParser getDefaultValueParser() {
		return defaultValueParser;
	}

	private DefaultParserProvider() {
		
		init() ;
	}

	@Override
	public AbstractValueParser getParser( String parserId )
	{
		if( parserId == null )
			return defaultValueParser ;
		
		AbstractValueParser parser = parserMap.get( parserId ) ;
		
		if( parser != null )
			return parser ;
		else
			return defaultValueParser ;
	}
	
	private void init()
	{
		parserMap = new HashMap<String, AbstractValueParser>() ;
		
		
		AbstractValueParser[] parserArr = { //new StringValueParser(),
											new DateParser(),
											new LinkArrayParser(),
											new DimensionParser(),
											new ScalarParser(),
											new TextsectionParser(),
											new IdentParser() } ;
		
		for( int i = 0 ; i < parserArr.length ; i++ )
			parserMap.put( parserArr[i].getId(), parserArr[i] ) ;
		
		parserMap.put( ParsedString.ID  , parserMap.get( ParsedIdent.ID ) ) ;
	}

}
